package com.mfz.users

import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import com.mfz.common.config.Config
import com.mfz.common.dbHelper.dbHelper
import com.mfz.common.definition.organization.GetUserFunction
import com.mfz.common.definition.symbol.Flag
import com.mfz.common.encryption.simpleEncrypt
import com.mfz.common.persistence.AbstractFactory
import com.mfz.common.persistence.AbstractPersistence
import com.mfz.common.units.ID
import com.mfz.users.definition.*

private const val SQL_USERS_TREE = "WITH RECURSIVE user_tree(id) AS (select id from users d where id = %d union select d.id from users d,user_tree ut where ut.id = d.parent_id) select * from user_tree"

//private const val SQL_USERS_BY_ROLE = "select * from users where %d = any(roles)";


class User private constructor() : AbstractPersistence(Companion), com.mfz.common.definition.organization.User {
	private lateinit var _ownerCompany: Company
	private lateinit var _users: List<User>
	private lateinit var _departments: List<Department>
	private lateinit var _roles: List<Role>

	/**
	 * 当前用户所有的权限字串
	 */
	private lateinit var powers: HashSet<Int>
	private var menu = EMPTY_MENU

	override fun completeReadFromDB() {
		_roles = Role.loadInvolveUsers(get(ROLES, emptyArray()))
		loadHasPermission()
	}

	override val isAvailable: Boolean
		get() = flag.notDelete && ownerCompany.isAvailable

	/**
	 * 返回当前用户对应的单位是否可用的
	 */
	fun isCompanyCanUse(user: User): Boolean {
		return when {
			dbHelper.queryWithOneValue<Int>("select flag from companys where id in (select company_id from users where id = ${user.id});") == Flag.DELETE.id -> false
			else -> true
		}
	}

	/**
	 * 此方法重新加载当前用户可用的权限内容
	 */
	private fun loadHasPermission() {
		powers = HashSet()
		for (role in _roles) {
			for (permission in role.get<Array<Int>>(PERMISSIONS, emptyArray())) {
				powers.add(permission)
			}
		}
	}

	override val ownerCompany: Company
		get() {
			if (!this::_ownerCompany.isInitialized) {
				_ownerCompany = Company.get(ID, get(COMPANY_ID, -1))!!
			}

			return _ownerCompany
		}
	override val encryptionKey: String
		get() = get(ENCRYPTION_KEY, "")

	override val department: Department
		get() = Department.get(ID, get(DEPARTMENT_ID, -1))!!

	override val departments: Collection<Department>
		get() {
			if (!this::_departments.isInitialized) {
				_departments = Department.loadInvolveUsers(id)
			}

			return _departments
		}

	/**
	 * 目前此方法为保留
	 */
	override val companys: Collection<Company>
		get() = arrayListOf()

	override val roles: Collection<Role> = _roles

	override val isSupperMan: Boolean
		get() = type == ADMINISTRATOR

	override val users: Collection<User>
		get() {
			if (!this::_users.isInitialized) {
				_users = User.getPersistences("id in ${String.format(SQL_USERS_TREE, id)}")
			}

			return _users
		}

	override val superior: User?
		get() = User.get(ID, get(PARENT_ID, -1))

	override fun login(password: String): Boolean {
		return simpleEncrypt(password) == get(PASSWORD, "")
	}

	override fun hasPermission(actionId: Int): Boolean {
		return powers.contains(actionId)
	}

	override fun getMenu(): String {
		if (isSupperMan) {
			return Config.getIns(OPERATOR_MENU).content.toJSONString()
		}

		if (menu == EMPTY_MENU) {
			menu =
				"{\"menu\":${loadMenuByPower(Config.getIns(OPERATOR_MENU).content.getJSONArray("menu"), powers).toJSONString()}}"
		}

		return menu
	}

	private fun loadMenuByPower(menu: JSONArray, powers: Set<Int>, setMenu: JSONArray? = null): JSONArray {
		val thisMenu = setMenu ?: JSONArray()

		menu.forEach {
			val subMenu = (it as JSONObject).clone() as JSONObject

			//如果当前对象的权限存在,没有指定ID的就是顶级对象
			if (!subMenu.containsKey(ID) || powers.contains(subMenu.getIntValue(ID))) {
				thisMenu.add(subMenu)

				if (it.containsKey("children")) {
					subMenu["children"] = JSONArray()

					loadMenuByPower(it.getJSONArray("children"), powers, subMenu["children"] as JSONArray?)
				} else {
					//为了于原有的对象进行脱离
					subMenu["operate"] = JSONArray()
					(it["operate"] as JSONArray).forEach { d ->
						if (d is JSONObject && powers.contains(d[ID])) {
							(subMenu["operate"] as JSONArray).add(d)
						}
					}
				}
			}

			if (!subMenu.containsKey(ID) && (subMenu.containsKey("children") && subMenu.getJSONArray("children").isEmpty())) {
				thisMenu.remove(subMenu)
			}
		}

		return thisMenu
	}

	override fun setRole(roleIds: Collection<Int>): Boolean {
		val tempRoles = mutableListOf<Role>()
		for (roleId in roleIds) {
			val role = Role.get(ID, roleId) ?: continue
			tempRoles.add(role)
		}
		_roles = tempRoles

		if (tempRoles.isEmpty()) {
			return false
		}

		loadHasPermission()
		return true
	}


	companion object : AbstractFactory<User>("users") {
		init {
			//需要使用用户类,必须获取的相关权限设置文件
			Config.createConfig(OPERATOR_MENU, "menu/OperatorMenu.json")
			useBuffer = true
		}

		fun getUsersByRole(roleId: Int): List<User> {
			return mutableListOf<User>().apply {
				for (user in getDatas()) {
					if (user.byPartOf(roleId)) {
						this.add(user)
					}
				}

			}
		}

		override fun createNewObject(): User {
			return User()
		}

		fun loadCompanyUsers(companyId: Int): List<User> {
			return getPersistences(" $COMPANY_ID = $companyId")
		}

		fun loadUsersInDepartment(departmentId: Int): List<User> {
			return getPersistences(" $DEPARTMENT_ID = $departmentId")
		}
	}

	private fun byPartOf(roleId: Int): Boolean {
		return get<Array<Int>>(ROLES, emptyArray()).contains(roleId)
	}

	override fun <T> set(name: String, value: T) {
		super.set(name,
			if (name == PASSWORD)
				simpleEncrypt(value.toString())
			else value
		)
	}
}


/**
 * 业务逻辑的获得一个用户的方法
 */
val getUserByIdFunction: GetUserFunction = fun(userId: Int): User? {
	return User.get(ID, userId)
}
